<!-- 表头和左边第一列固定的表格 -->
<template lang="pug">
section
  g-h.container
    div.container-wrapper(ref="fixedWrapper")
      th.th.fixed(ref="fixed") {{ headList[0].title }}
      div.fixed-column(ref="fixedColumn" v-scroll="scroll")
        tr.tr(
            v-for="(item, i) in firstColumn"
            :key="i"
            :style="columnBodyStyleMap[headList[0].field]"
            @click="$emit('click-row', body.list[i], i)"
          )
          td.td {{ item }}

    table.stat-table(ref="table")
      thead.thead(ref="thead" v-scroll="scroll")
        tr
          th.th(
              v-for="(item, i) in headList.slice(1)"
              :key="i"
              v-if="item.checked"
              ) {{ item.title }}
      tbody.tbody(
            v-if="body.list"
            v-scroll="scroll"
            ref="tbody"
            )
        tr.tr(
            v-for="(row, i) in body.list"
            :key="i"
            @click="$emit('click-row', row, i)"
            )
          td.td(
              v-for="(field, j) in checkedHeadList.slice(1)"
              :key="j"
              :rowspan="rowspan(i, field)"
              )
            input.input(
                v-if="inputHeader[field]"
                v-model="row[field]"
                @click.stop=""
                @blur="$emit('check-input', row[field], i, field)"
                :disabled="disabled"
                )
            div.td-content(
                v-else-if="row[field] != undefined"
                :style="columnBodyStyleMap[field]"
                ) {{ row[field] }}
  div.loading(v-if="isLoading")
    icon-loading
</template>

<script>
/*
  事件
    click-row     点击一行
    check-input   检查输入数据
*/

export default {
  name: "StatTable",
  props: {
    /* 
      表头列表
      示例:
      [
        { field: "name", title: "合同名称", checked: true, isInput: true },
        { field: "id", title: "合同ID", checked: false },
        { field: "code", title: "合同编号", checked: true },
      ]
    */
    headList: {
      type: Array,
      default: () => [],
    },

    /* 
      表格数据
      示例:
      {
        list: [
          { userRealName: "", id: 123 },
        ],
      }
    */
    body: {
      type: Object,
      default: () => {},
    },

    // 是否显示载入中
    isLoading: {
      type: Boolean,
      default: false,
    },

    // 是否禁用输入框
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      hackAdd: false,
      scrollTop: 0,
      scrollLeft: 0,
    }
  },
  computed: {
    checkedHeadList() {
      let checked = []
      for (let item of this.headList) {
        if (item.checked) {
          checked.push(item.field)
        }
      }
      return checked
    },
    inputHeader() {
      let m = {}
      for (let item of this.headList) {
        if (item.isInput) {
          m[item.field] = true
        }
      }
      return m
    },
    firstColumn() {
      let lst = new Array(this.body.list.length)
      let i = 0
      for (let item of this.body.list) {
        lst[i] = item[this.checkedHeadList[0]]
        i++
      }
      return lst
    },
    columnBodyStyleMap() {
      let m = {}
      for (let item of this.headList) {
        if (item.bodyStyle) {
          m[item.field] = item.bodyStyle
        }
      }
      return m
    },
  },

  methods: {
    rowspan(row, field) {
      if (this.body.spanTable) {
        let m = this.body.spanTable[row]
        if (m[field]) {
          return m[field]
        } else {
          return 1
        }
      } else {
        return 1
      }
    },
    scroll(e) {
      let left = e.target.scrollLeft
      let top = e.target.scrollTop
      let thead = this.$refs.thead
      let c = this.$refs.fixedColumn
      let tbody = this.$refs.tbody

      switch (e.target.tagName) {
        case "TBODY":
          thead.scrollLeft = left
          c.scrollTop = top
          break

        case "THEAD":
          tbody.scrollLeft = left
          break
      }
    },
    hackUpdateTable() {
      // hack: in order to work in android 4.4
      let w = this.$refs.fixed.clientWidth
      let wrapper = this.$refs.fixedWrapper
      wrapper.style.width = `${w}px`
      wrapper.style.minWidth = `${w}px`

      // hack: add more space when there are few columns
      let thead = this.$refs.thead
      let tr = thead.querySelector("tr")
      if (tr.clientWidth < thead.clientWidth) {
        let thList = thead.querySelectorAll("th")
        let delta = (thead.clientWidth - tr.clientWidth) / (thList.length + 1)
        for (let item of thList) {
          item.style.minWidth = item.clientWidth + delta + "px"
        }
      }

      let table = this.$refs.table
      let allWidth = document.documentElement.clientWidth
      table.style.width = `${allWidth - w}px`
    },

    refresh() {
      let fixed = this.$refs.fixed
      // skip when the table is invisible, e.g. in an invisible tab
      if (this.body.list.length === 0 || fixed.clientWidth === 0) {
        return
      }

      // hack: in order to work in android 4.4
      fixed.style.display = "block"
      let firstLeft = this.$refs.fixedColumn.querySelector(".td")
      // hack: need to add 10, because otherwise the top-left header might show ellipssis
      let w = Math.max(fixed.clientWidth, firstLeft.clientWidth)
      // hack: otherwise everytime input changes, the column width increases
      if (!this.hackAdd) {
        w += 10
        this.hackAdd = true
      }
      let wrapper = this.$refs.fixedWrapper
      wrapper.style.width = `${w}px`
      wrapper.style.minWidth = `${w}px`

      let thead = this.$refs.thead
      let headList = thead.querySelectorAll(".th")

      let tbody = this.$refs.tbody
      let firstRow = tbody.querySelector(".tr")
      let firstRowList = firstRow.querySelectorAll(".td")

      let th, td
      for (let i = 0; i < headList.length; i++) {
        th = headList[i]
        td = firstRowList[i]
        if (th.clientWidth > td.clientWidth) {
          td.style.minWidth = th.clientWidth + "px"
        } else if (th.clientWidth < td.clientWidth) {
          th.style.minWidth = td.clientWidth + "px"
        }
      }

      this.hackUpdateTable()
    },
  },

  mounted() {
    this.hackUpdateTable()
    window.addEventListener("resize", this.refresh)
  },

  beforeDestroy() {
    window.removeEventListener("resize", this.refresh)
  },

  updated() {
    this.refresh()
  },

  activated() {
    let tbody = this.$refs.tbody
    tbody.scrollTop = this.scrollTop
    tbody.scrollLeft = this.scrollLeft
  },
  deactivated() {
    let tbody = this.$refs.tbody
    this.scrollTop = tbody.scrollTop
    this.scrollLeft = tbody.scrollLeft
  },

}
</script>

<style lang="stylus" scoped>

.c-root
  width: 100%
  height: 100%
  position: relative

.loading
  position: absolute
  top: 50%
  left: 50%
  transform(translate(-50%,-50%))

.container
  width: 100%
  height: 100%
  &-wrapper
    height: 100%

// @supports not (position: sticky)
  // .hack
    // padding-right: 5rem

.stat-table
  width: 100%
  height: 100%
  table-layout: fixed
  border-collapse: collapse
  // box-shadow: 0 1px 5px grey500

.thead
  width: 100%
  display: block
  overflow-x: scroll
  &::-webkit-scrollbar
    display: none
  table-head()

.tbody
  height: calc(100% - 2rem)
  display: block
  overflow: scroll
  &::-webkit-scrollbar
    display: none

.fixed
  table-head()

.tr
  line-height: 1.7rem // hack: in order to work in android 4.4
  height: 39px

.th
  color: grey600
  text-align: center
  text-ellipsis()

.td
  text-align: start
  &-content
    text-ellipsis()

.th, .td
  padding: 0.4rem 0.6rem
  max-width: 12rem
  vertical-align: middle
  // white-space: nowrap

.input
  // width: 100%
  width: 4rem
  text-align: start

// TODO can't  be put before .th, I don't know why
.fixed-column
  height: calc(100% - 2rem)
  overflow-x: scroll
  overflow-y: hidden
  white-space: nowrap
  &::-webkit-scrollbar
    display: none
  // & .td
    // text-ellipsis()

</style>
